package com.hiss.basic.admin.handler;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpStatus;
import com.hiss.basic.starter.core.exception.BusinessException;
import com.hiss.basic.starter.core.model.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 认证失败
     */
    @ExceptionHandler(NotLoginException.class)
    public R<Void> notLoginException(NotLoginException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 认证失败={}", requestURI, e.getMessage());
        return R.failure(HttpStatus.HTTP_UNAUTHORIZED, "Authentication failed");
    }

    /**
     * 角色权限异常
     */
    @ExceptionHandler(NotRoleException.class)
    public R<Void> notRoleException(NotRoleException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 角色权限校验失败={}", requestURI, e.getMessage());
        return R.failure(HttpStatus.HTTP_FORBIDDEN, "Access denied");
    }

    /**
     * 权限码异常
     */
    @ExceptionHandler(NotPermissionException.class)
    public R<Void> notPermissionException(NotPermissionException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 权限码校验失败={}", requestURI, e.getMessage());
        return R.failure(HttpStatus.HTTP_FORBIDDEN, "Access denied");
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R<Void> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 不支持请求={}", requestURI, e.getMethod());
        return R.failure(HttpStatus.HTTP_BAD_METHOD, e.getMessage());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public R<Void> businessException(BusinessException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 业务异常={}", requestURI, e.getMessage());
        return R.failure(e.getCode(), e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public R<Void> bindException(BindException e) {
        String message = CollUtil.join(e.getAllErrors(), ", ", DefaultMessageSourceResolvable::getDefaultMessage);
        return R.failure(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R<Void> constraintViolationException(ConstraintViolationException e) {
        String message = CollUtil.join(e.getConstraintViolations(), ", ", ConstraintViolation::getMessage);
        return R.failure(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<Void> methodArgumentNotValidException(MethodArgumentNotValidException e) {
        String message = CollUtil.join(e.getBindingResult().getAllErrors(), ", ", DefaultMessageSourceResolvable::getDefaultMessage);
        return R.failure(message);
    }

    /**
     * 运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public R<Void> runtimeException(RuntimeException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 运行时异常", requestURI, e);
        return R.failure(e.getMessage());
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public R<Void> exception(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址={} 系统异常", requestURI, e);
        return R.failure(e.getMessage());
    }
}
